//
// Created by 31897 on 2021/11/2.
//

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <time.h>

//                        0    1    2    3    4    5    6    7    8    9    -   off
unsigned char tube[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f,0xff};

unsigned char addr[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

int isLegal(char* clock){
    //小时超过29
    if(clock[0]>'2'||clock[0]<'0'){
        return 0;
    }
    //小时数在24-29
    if(clock[0]=='2'||clock[1]>'3'){
        return 0;
    }
    //第2位不在0-9之间
    if(clock[1]<'0'||clock[1]>'9'){
        return 0;
    }
    //第5位不在0-9之间
    if(clock[4]<'0'||clock[4]>'9'){
        return 0;
    }
    //第8位不在0-9之间
    if(clock[7]<'0'||clock[7]>'9'){
        return 0;
    }
    //第3位和第6位不是冒号
    if(clock[2]!=':'||clock[5]!=':'){
        return 0;
    }
    //分数超过59
    if(clock[3]>'5'||clock[3]<'0'){
        return 0;
    }
    //秒数超过59
    if(clock[6]>'5'||clock[6]<'0'){
        return 0;
    }
    return 1;
}

int moving(char* clock){
    //秒加一
    if(clock[7]!='9'){
        clock[7]++;
        return 0;
    } else{//秒进位
        clock[7]='0';
        if(clock[6]!='5'){
            clock[6]++;
        } else{//分加一
            clock[6]='0';
            if(clock[4]!='9'){
                clock[4]++;
            } else{//分进位
                clock[4]='0';
                if(clock[3]!='5'){
                    clock[3]++;
                } else{
                    clock[3]='0';
                    //时加一
                    if(clock[0]!='2'&&clock[1]!='9') {
                        clock[1]++;
                    } else if(clock[0]=='2'&&clock[1]!='3'){
                        clock[1]++;
                    } else if(clock[0]!='2'&&clock[1]=='9'){//时进位
                        clock[1] = '0';
                        clock[0]++;
                    } else{//下一天
                        clock[1]=clock[0]='0';
                    }
                }
            }
        }
    }
}

int main(int argc, char *argv[])
{
    int num=0;
    int i=0,j=0;
    int mem_fd;
    char time[] = "";
    unsigned char *cpld;
    clock_t start, finish;
    strcpy(time,argv[1]);
    mem_fd = open("/dev/mem", O_RDWR);

    cpld = (unsigned char*)mmap(NULL,(size_t)0x10,PROT_READ | PROT_WRITE | PROT_EXEC,MAP_SHARED,mem_fd,(off_t)(0x8000000));

    if(cpld == MAP_FAILED)
       return;

    // 参数判断是否合法
    if(!isLegal(time)){
        printf("input error!");
        return 0;
    }

    while(1)
    {
        start = clock();
        for(j=0;j<245*4;j++)
        {
            switch(i)
            {
                case 0:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址  (0xe6<<1)为地址
                    *(cpld+(0xe4<<1)) = tube[time[i]='0'];
                    break;

                case 1:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址
                    *(cpld+(0xe4<<1)) = tube[time[i]='0'];
                    break;

                case 2:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址
                    *(cpld+(0xe4<<1)) = tube[10];
                    break;

                case 3:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址
                    *(cpld+(0xe4<<1)) = tube[time[i]='0'];
                    break;

                case 4:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址  (0xe6<<1)为地址
                    *(cpld+(0xe4<<1)) = tube[time[i]='0'];
                    break;

                case 5:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址
                    *(cpld+(0xe4<<1)) = tube[10];
                    break;

                case 6:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址
                    *(cpld+(0xe4<<1)) = tube[time[i]='0'];
                    break;

                case 7:
                    *(cpld+(0xe6<<1)) = addr[i];   //数码管地址
                    *(cpld+(0xe4<<1)) = tube[time[i]='0'];
                    break;

                default:
                    break;
            }
            

            //延时显示各个数字
            usleep(1000);

            if((++i)==8)
                i=0;

            

            
        }
        moving(time);
        finish = clock();
        usleep(1000000-finish+start);  
    }

    munmap(cpld,0x10);

    close(mem_fd);

    return 0;
}
